class Fib(object):
    def __init__(self):
        self.__a = 0
        self.__b = 1

    def __str__(self):
        return f'Fib instance: {self.__a}, {self.__b}'

    # __iter__ 返回被迭代的对象
    def __iter__(self):
        return self

    # __next__ 每次迭代时调用的方法
    def __next__(self):
        self.__a, self.__b = self.__b, self.__a + self.__b
        if self.__a > 100:
            raise StopIteration()
        return self.__a

    def __getattr__(self, item):
        return 'get no found attribute %s' % item

    # 使用 __getitem__ 方法可以返回按照序号返回结果
    def __getitem__(self, index):
        if isinstance(index, int):
            a, b = self.__a, self.__b
            for i in range(index):
                a, b = b, a + b
            return a
        if isinstance(index, slice):
            start, stop, step = index.start, index.stop, index.step
            if start is None:
                start = 0
            a, b = 1, 1
            L = []
            for i in range(stop):
                if i >= start:
                    L.append(a)
                    a, b = b, a + b
            return L

    @property
    def get_kind(self):
        return self.__kind

    @get_kind.setter
    def set_kind(self, kind):
        if not isinstance(kind, int):
            raise TypeError('kind must be int')
        self.__kind = kind

    __repr__ = __str__


# 隐式调用 Fib 对象 __iter__ 方法返回值的 __next__ 方法
for x in Fib():
    print(x)

fib = Fib()
print(fib)

# 调用 fib[index] 时会隐式调用 __getitem__ 方法并传入 index
print(fib[1])
print(fib[2])
print(fib[3])
print(fib[0:5])
# 在调用非法属性是会 隐式调用 __getattr__ 方法
print(fib.xkds)

# 使用 @property 和 @setter 装饰 属性的 get 和 set 并添加校验

fib.set_kind = 1
print(fib.get_kind)
